Embedded systems are usually computer-based systems, and are designed and implemented for performing a predefined and specific activity. As such, their designs and complexities vary greatly, although they do share some common hardware and software structures. An embedded system, as well as a typical computer system, has several major hardware components connected together by buses. These components may include central processing units (CPUs), peripheral devices providing the interface between the system an the external world, buses (e.g., CPU bus, PCI bus, SDRAM bus, etc.) connecting various system components among themselves and sometimes between systems that reside close to each other, and system controllers implementing various bus interfaces in the system, providing interrupt and timer support, and providing address decoding and re-mapping.
The basic operations performed in a computer system are fetch (or read) from a specified location and store (or write) to a specified location. Each location is identified by a unique address assigned to it in the bus it is located in, hence creating an address map for that bus, and when combined with other subsystems, an address map is defined for the whole system. However, each bus may view the system differently. For example, devices may reside on different buses and have different address schemes and electrical characteristics. Yet, these diverse devices may need to communicate among themselves.
When a device on bus A (for example a PCI bus) wishes to access a device in bus B (for example a device bus), it places on its bus a request including the address of the device it wishes to access. It is the responsibility of the system controller to identify that request, identify the bus for which the request is intended (also called address decoding), and to perform the necessary electrical, address and data conversions for placing the request on the destination bus.
For example, a CPU, in order to access a device residing in the PCI bus, puts its request on the CPU bus. The system controller identifies that request, decodes the address, and determines that it is an address assigned to the PCI bus. The system controller further performs the necessary conversions and places the converted request on the PCI bus to be handled by the destination PCI device.
In terms of initializing such a system, after a processor has been reset, it has no knowledge of the system it is in, therefore it always accesses to a specific address (0xFFF00100 in power PC) and executes the command written there. It is the responsibility of the designer to place the boot code in that address. And, more precisely, to preset the system controller such that this address when placed on the CPU bus will be transferred to the bus where the boot code resides.
In a PC, this is the task of the BIOS as can be seen on the screen when booting the PC. System boot process includes among other things, programming the system controller for correct address space decoding, performing power-on self-test, initializing various components in the system, obtaining the system image, creating the sufficient environment for booting it, and then transfer control to the operating system.
One of the issues in a multi-processor embedded environment, such as in a communications or computer device, is the software boot sequence. This issue is especially noticed in master-slaves systems where one central processor is used to manage the system and to synchronize the software versions and software download processes of its slaves. In such systems, it is common to find a small and robust boot-loader software which is embedded into each processor module and is being executed by the local processor at boot time. The major task of such a boot-loader software is usually to perform the preliminary initializations (both software and hardware) required for creating a communication channel with the master, synchronize themselves with the master software, and then wait for further instructions from the master which usually starts loading the “real” software to the slaves, a cumbersome process by itself. Although a distributed boot-loader is implemented in many systems, it is far from being trivial, and requires careful planning of software upgrade process, error recovery, inter boot-loaders communication and more. Needed are new methods and apparatus for booting processors in multiprocessor and other systems.